﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using Wechat.Webapi.Business;
using Wechat.Webapi.Modal;
using Wechat.Webapi.Modal.LoginEntity;

namespace Wechat.Webapi
{

    public class WeixinClient
    {
        public Client client;
        private Dictionary<string, Contact> contactDict = new Dictionary<string, Contact>();
        private string cookiePath = AppDomain.CurrentDomain.BaseDirectory + "autoLoginCookie";
        private string DeviceId = "";

        public static Queue<MessageInfo> msgs = new Queue<MessageInfo>();
        [STAThread]
        public void Start()
        {

            client = new Client();
            string cookie = null;
            //获取登陆之后记录的cookie，实现推送手机端登陆，取代扫码
            //若不需要，注释掉以下代码即可
            if (File.Exists(cookiePath))
            {
                StreamReader sr = new StreamReader(cookiePath, Encoding.UTF8);
                cookie = sr.ReadLine();
                sr.Close();
            }
            client.ExceptionCatched += Client_ExceptionCatched; ;
            client.GetLoginQrCodeComplete += Client_GetLoginQrCodeComplete; ;
            client.CheckScanComplete += Client_CheckScanComplete; ;
            client.LoginComplete += Client_LoginComplete; ;
            client.BatchGetContactComplete += Client_BatchGetContactComplete; ;
            client.GetContactComplete += Client_GetContactComplete; ;
            client.MPSubscribeMsgListComplete += Client_MPSubscribeMsgListComplete; ;
            client.LogoutComplete += Client_LogoutComplete; ;
            client.ReceiveMsg += Client_ReceiveMsg; ;
            client.DelContactListComplete += Client_DelContactListComplete; ;
            client.ModContactListComplete += Client_ModContactListComplete;
            Console.WriteLine("贾维斯已经苏醒");
            client.Start(cookie);
            //同步联系人
         }



        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine(e.ToString());
        }

        private void Client_ModContactListComplete(object sender, TEventArgs<List<Contact>> e)
        {
            Console.WriteLine("接收修改联系人信息");
            List<Contact> lis = new List<Contact>();

            foreach (var item in e.Result)
            {
                contactDict[item.UserName] = item;
                lis.Add(item);
            }
            WeinxinSqlBusiness.SaveConnact(lis, this.client.user.Uin);

        }

        private void Client_DelContactListComplete(object sender, TEventArgs<List<DelContactItem>> e)
        {
 
            Console.WriteLine("接收删除联系人信息");
        }

        private void Client_ReceiveMsg(object sender, TEventArgs<List<AddMsg>> e)
        {
            try
            {
                foreach (var item in e.Result)
                {
                    switch (item.MsgType)
                    {
                        case MsgType.MM_DATA_TEXT:
                            if (!contactDict.Keys.Contains(item.FromUserName))
                            {
                                //不包含（一般为群）则需要我们主动拉取信息
                                client.GetBatchGetContactAsync(item.FromUserName);

                            }
                            else if (!contactDict.Keys.Contains(item.ToUserName))
                            {
                                client.GetBatchGetContactAsync(item.ToUserName);

                            }
                            else
                            {

                                if (item.FromUserName.StartsWith("@@"))
                                {
                                    //群消息，内容格式为[群内username];<br/>[content]，例如Content=@ffda8da3471b87ff22a6a542c5581a6efd1b883698db082e529e8e877bef79b6:<br/>哈哈
                                    string[] content = item.Content.Split(new string[] { ":<br/>" }, StringSplitOptions.RemoveEmptyEntries);
                                    string qName = contactDict[item.FromUserName].NickName;
                                    string Name = contactDict[item.FromUserName].MemberDict[content[0]].NickName;//群里发消息的昵称
                                    var ass = contactDict[item.FromUserName].MemberDict[content[0]];

                                    Console.WriteLine(qName + "：" + Name + "：" + content[1]);

                                    //0yyyyy client.SendMsgAsync("收到！@" + Name, item.FromUserName);
                                    msgs.Enqueue(new MessageInfo
                                    {
                                        QNickName = qName,
                                        QUserName = contactDict[item.FromUserName].UserName,
                                        QRemarkName = contactDict[item.FromUserName].RemarkName,
                                        FromNiCkName = contactDict[item.FromUserName].MemberDict[content[0]].NickName,
                                        FromUserName = contactDict[item.FromUserName].MemberDict[content[0]].UserName,
                                        FromRemarkName = contactDict[item.FromUserName].MemberDict[content[0]].NickName,
                                        ToNiCkName = this.client.user.NickName,
                                        ToUserName = this.client.user.UserName,
                                        ToRemarkName = "Me",
                                        MsgContent = content[1]
                                    });
                                }
                                else
                                {
                                    string qNickName = "";
                                    string qUserName = "";
                                    string RemarkName = "";
                                    string fromeNickname = contactDict[item.FromUserName].NickName;
                                    string username = contactDict[item.FromUserName].UserName;
                                    string fromRemarkName = contactDict[item.FromUserName].RemarkName;

                                    if (this.client.user.UserName == item.FromUserName && item.ToUserName.StartsWith("@@"))
                                    {
                                        qUserName = item.ToUserName;
                                        qNickName = contactDict[item.FromUserName].NickName;
                                        RemarkName = contactDict[item.FromUserName].RemarkName;
                                        fromeNickname = this.client.user.NickName;
                                        username = this.client.user.UserName;
                                        fromRemarkName = "Me";
                                    }
                                    string content = item.Content;
                                    msgs.Enqueue(new MessageInfo
                                    {
                                        QNickName = qNickName,
                                        QUserName = qUserName,
                                        QRemarkName = RemarkName,
                                        FromNiCkName = fromeNickname,
                                        FromUserName = username,
                                        FromRemarkName = fromRemarkName,
                                        ToNiCkName = contactDict[item.ToUserName].NickName,
                                        ToUserName = item.ToUserName,
                                        ToRemarkName = contactDict[item.ToUserName].RemarkName,
                                        MsgContent = content
                                    });
                                    Console.WriteLine(fromeNickname + "：" + item.Content);
                                }
                                ////自动回复
                                //if (item.Content == "666666")
                                //{
                                //    client.SendMsgAsync("双击666！", item.FromUserName);
                                //}
                            }
                            break;
                        case MsgType.MM_DATA_HTML:
                            break;
                        case MsgType.MM_DATA_IMG:
                            break;
                        case MsgType.MM_DATA_PRIVATEMSG_TEXT:
                            break;
                        case MsgType.MM_DATA_PRIVATEMSG_HTML:
                            break;
                        case MsgType.MM_DATA_PRIVATEMSG_IMG:
                            break;
                        case MsgType.MM_DATA_VOICEMSG:
                            break;
                        case MsgType.MM_DATA_PUSHMAIL:
                            break;
                        case MsgType.MM_DATA_QMSG:
                            break;
                        case MsgType.MM_DATA_VERIFYMSG:
                            //自动加好友，日限额80个左右，请勿超限额多次调用，有封号风险
                            //client.VerifyUser(item.RecommendInfo);
                            break;
                        case MsgType.MM_DATA_PUSHSYSTEMMSG:
                            break;
                        case MsgType.MM_DATA_QQLIXIANMSG_IMG:
                            break;
                        case MsgType.MM_DATA_POSSIBLEFRIEND_MSG:
                            break;
                        case MsgType.MM_DATA_SHARECARD:
                            break;
                        case MsgType.MM_DATA_VIDEO:
                            break;
                        case MsgType.MM_DATA_VIDEO_IPHONE_EXPORT:
                            break;
                        case MsgType.MM_DATA_EMOJI:
                            break;
                        case MsgType.MM_DATA_LOCATION:
                            break;
                        case MsgType.MM_DATA_APPMSG:
                            break;
                        case MsgType.MM_DATA_VOIPMSG:
                            break;
                        case MsgType.MM_DATA_STATUSNOTIFY:
                            switch (item.StatusNotifyCode)
                            {
                                case StatusNotifyCode.StatusNotifyCode_READED:
                                    break;
                                case StatusNotifyCode.StatusNotifyCode_ENTER_SESSION:
                                    break;
                                case StatusNotifyCode.StatusNotifyCode_INITED:
                                    break;
                                case StatusNotifyCode.StatusNotifyCode_SYNC_CONV:
                                    //初始化的时候第一次sync会返回最近聊天的列表
                                    client.GetBatchGetContactAsync(item.StatusNotifyUserName);
                                    break;
                                case StatusNotifyCode.StatusNotifyCode_QUIT_SESSION:
                                    break;
                                default:
                                    break;
                            }
                            break;
                        case MsgType.MM_DATA_VOIPNOTIFY:
                            break;
                        case MsgType.MM_DATA_VOIPINVITE:
                            break;
                        case MsgType.MM_DATA_MICROVIDEO:
                            break;
                        case MsgType.MM_DATA_SYSNOTICE:
                            break;
                        case MsgType.MM_DATA_SYS:
                            //系统消息提示，例如完成好友验证通过，建群等等，提示消息“以已经通过了***的朋友验证请求，现在可以开始聊天了”、“加入了群聊”
                            //不在字典，说明是新增，我们就主动拉取加入联系人字典
                            if (!contactDict.Keys.Contains(item.FromUserName))
                            {
                                client.GetBatchGetContactAsync(item.FromUserName);
                            }
                            break;
                        case MsgType.MM_DATA_RECALLED:
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception err)
            {
                Console.WriteLine("异常：" + err.Message);
            }
        }

        private void Client_LogoutComplete(object sender, TEventArgs<User> e)
        {
            Console.WriteLine("已登出");
        }

        private static void Client_MPSubscribeMsgListComplete(object sender, TEventArgs<List<MPSubscribeMsg>> e)
        {
            Console.WriteLine("获取公众号文章，总数：" + e.Result.Count);
        }

        private void Client_GetContactComplete(object sender, TEventArgs<List<Contact>> e)
        {
            List<Contact> lis = new List<Contact>();

            Console.WriteLine("获取联系人列表（包括公众号，联系人），总数：" + e.Result.Count);
            foreach (var item in e.Result)
            {
                if (!contactDict.Keys.Contains(item.UserName))
                {
                    contactDict.Add(item.UserName, item);
                    Console.WriteLine($"Client_GetContactComplete获取联系人 ：{item.UserName}");
                    lis.Add(item);
                }
               

                //联系人列表中包含联系人，公众号，可以通过参数做区分
                if (item.VerifyFlag != 0)
                {
                    //个人号
                }
                else
                {
                    //公众号
                }
            }
            //如果获取完成
            if (client.IsFinishGetContactList)
            {

            }
            WeinxinSqlBusiness.SaveConnact(lis, this.client.user.Uin);
        }

        private void Client_BatchGetContactComplete(object sender, TEventArgs<List<Contact>> e)
        {
            Console.WriteLine("拉取联系人信息，总数：" + e.Result.Count);
            List< Contact > lis=new List<Contact>();
            foreach (var item in e.Result)
            {
                if (!contactDict.Keys.Contains(item.UserName))
                {
                    Console.WriteLine(item.UserName, item.Uin);
                    contactDict.Add(item.UserName, item);
                    lis.Add(item);
                }
            }
            WeinxinSqlBusiness.SaveConnact(lis, this.client.user.Uin);

         }

        private async void Client_LoginComplete(object sender, TEventArgs<User> e)
        {
            string cookie = client.GetLastCookie();
            Console.WriteLine("登陆成功：" + e.Result.NickName);
            Console.WriteLine("========已记录cookie，下次登陆将推送提醒至手机，取代扫码========");
            using (StreamWriter sw = new StreamWriter(cookiePath, false))
            {
                sw.WriteLine(cookie);
            }
            UserInfo user = this.client.user.ToJson().ToObject<UserInfo>();
            user.syncKey = this.client.syncKey.ToString();
            user.Uuid = this.client.uuid;
            user.Sid = this.client.baseRequest.Sid;
            user.Skey = this.client.baseRequest.Skey;

            WeinxinSqlBusiness.Login(user);
            //启动定时同步消息
            AddMsg(client.user.Uin);
        }

        private void Client_CheckScanComplete(object sender, TEventArgs<System.Drawing.Image> e)
        {
            Console.WriteLine("用户已扫码");
        }

        private void Client_GetLoginQrCodeComplete(object sender, TEventArgs<System.Drawing.Image> e)
        {
            Console.WriteLine("已获取登陆二维码");

        }

        private void Client_ExceptionCatched(object sender, TEventArgs<Exception> e)
        {
            if (e.Result is GetContactException)
            {
                Console.WriteLine("获取好友列表异常：" + e.Result.ToString());
                return;
            }

            if (e.Result is OperateFailException)
            {
                Console.WriteLine("异步操作异常：" + e.Result.ToString());
                return;
            }

            Console.WriteLine("异常：" + e.Result.ToString());
        }


 

        /// <summary>
        /// 定时同步消息
        /// </summary>
        /// <param name="uin"></param>
        /// <returns></returns>
        public async Task AddMsg(string uin)
        {
            Console.WriteLine("开始定时同步消息：" + uin);

            while (true)
            {
                await Task.Delay(10000);

                int lenth = msgs.Count;
                List<MessageInfo> msgss = new List<MessageInfo>();
                while (lenth > 0)
                {
                    MessageInfo aaa = msgs.Dequeue();
                    msgss.Add(aaa);
                    lenth--;

                }

                if (msgss.Count > 0)
                {
                    await WeinxinSqlBusiness.AddMessgs(msgss, uin);
                    msgss.Clear();
                }
            }
        }
    }
}
